/*-------------------------------------------------------------------------
 *
 * dest.h
 *	  支持通信目的地
 *
 * 每当后台执行返回元组的查询时，结果必须发送到某个地方. 例如:
 *
 *	  - stdout 仅在我们运行一个独立后台（没有后台进程）并
 *		将结果返回给交互用户时为目的地.
 *
 *	  - 当我们运行一个具有前端的后台并且前端执行
 *		PQexec() 或 PQfn() 时，远程进程是目的地.
 *		在这种情况下，结果通过 backend/libpq 中的函数发送
 *		到前端.
 *
 *	  - 当系统内部执行查询时，DestNone 是目的地.
 *		结果将被丢弃.
 *
 * dest.c 定义了三个实现目的地管理的函数:
 *
 * BeginCommand: 在命令开始时初始化目的地.
 * CreateDestReceiver: 返回指向特定于目的地的接收函数结构的指针.
 * EndCommand: 在命令结束时清理目的地.
 *
 * BeginCommand/EndCommand 每接收到一个 SQL 查询执行一次.
 *
 * CreateDestReceiver 返回适合于指定目的地的接收器对象.
 * 执行器以及可以返回元组的公用语句，将结果的 DestReceiver* 指针传递给它.
 * 每次执行器运行或公用执行调用接收器的 rStartup 方法，然后接收
 * receiveSlot 方法（零次或多次），然后是 rShutdown 方法.
 * 同一个接收器对象可以多次重用；最终，它通过调用
 * 其 rDestroy 方法被销毁.
 *
 * 在某些情况下，接收器对象需要额外的参数，这些参数必须在
 * 调用 CreateDestReceiver 后传递给它们. 由于不同接收器类型的参数集
 * 不同，这不是由此模块处理的，而是由调用代码直接调用
 * 特定于接收器类型的函数来处理.
 *
 * CreateDestReceiver 返回的 DestReceiver 对象可以是一个静态分配的
 * 对象（对于不需要本地状态的目的地类型），在这种情况下,
 * rDestroy 是一个空操作. 或者它可以是一个 palloc 的对象，具有 DestReceiver
 * 作为其第一个字段，并包含其他字段（参见 printtup.c 以获取一个示例）.
 * 这些额外字段然后可以通过传递给它们的 DestReceiver* 指针进行类型转换
 * 从而被 DestReceiver 函数访问. palloc 对象由 rDestroy 方法 pfree.
 * 注意，CreateDestReceiver 的调用者应该小心在长生命周期的内存上下文中执行
 * 该操作，以便接收器对象在仍然需要时不会消失.
 *
 * 特别规定: None_Receiver 是 DestNone 目的地的永久可用接收器对象.
 * 这避免了在门户和光标操控中的无用创建/销毁调用.
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/tcop/dest.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef DEST_H
#define DEST_H

#include "executor/tuptable.h"
#include "tcop/cmdtag.h"


/* 用于命令完成标签的缓冲区大小 */
#define COMPLETION_TAG_BUFSIZE	64


/* ----------------
 *		CommandDest 是识别所需目标的简单方式。将来这可能需要改进。
 *
 * 注意: 仅 DestNone、DestDebug、DestRemote 的值是全球变量 whereToSendOutput 的合法值。其他值可以用作单个命令的目标。
 * ----------------
 */
typedef enum
{
	DestNone,					/* 结果被丢弃 */
	DestDebug,					/* 结果发送到调试输出 */
	DestRemote,					/* 结果发送到前端进程 */
	DestRemoteExecute,			/* 在执行命令中发送到前端 */
	DestRemoteSimple,			/* 发送到前端，无目录访问 */
	DestSPI,					/* 结果发送到 SPI 管理器 */
	DestTuplestore,				/* 结果发送到 Tuplestore */
	DestIntoRel,				/* 结果发送到关系 (SELECT INTO) */
	DestCopyOut,				/* 结果发送到 COPY TO 代码 */
	DestSQLFunction,			/* 结果发送到 SQL语言函数管理器 */
	DestTransientRel,			/* 结果发送到瞬态关系 */
	DestTupleQueue				/* 结果发送到元组队列 */
} CommandDest;

/* ----------------
 *		DestReceiver 是针对特定目标的本地状态的基本类型。
 *		在最简单的情况下，没有状态信息，仅有执行器必须调用的函数指针。
 *
 * 注意: receiveSlot 例程必须传递一个包含与 rStartup 例程给定的 TupleDesc 相同的槽。它返回布尔值，其中 "true" 值表示 "继续处理"，"false" 值表示 "提前停止，就好像我们已经到达扫描结束"。
 * ----------------
 */
typedef struct _DestReceiver DestReceiver;

struct _DestReceiver
{
	/* 针对每个要输出的元组被调用: */
	bool		(*receiveSlot) (TupleTableSlot *slot,
								DestReceiver *self);
	/* 每个执行器运行的初始化和关闭: */
	void		(*rStartup) (DestReceiver *self,
							 int operation,
							 TupleDesc typeinfo);
	void		(*rShutdown) (DestReceiver *self);
	/* 销毁接收器对象本身（如果动态分配） */
	void		(*rDestroy) (DestReceiver *self);
	/* 此接收器的 CommandDest 代码 */
	CommandDest mydest;
	/* 私有字段可能出现在此之后... */
};

extern PGDLLIMPORT DestReceiver *None_Receiver; /* 永久接收器用于
												 * DestNone */

/* 主要的目标管理函数 */

extern void BeginCommand(CommandTag commandTag, CommandDest dest);
extern DestReceiver *CreateDestReceiver(CommandDest dest);
extern void EndCommand(const QueryCompletion *qc, CommandDest dest,
					   bool force_undecorated_output);
extern void EndReplicationCommand(const char *commandTag);

/* 附属于目标管理的其他函数或多或少。 */

extern void NullCommand(CommandDest dest);
extern void ReadyForQuery(CommandDest dest);

#endif							/* DEST_H */
